/********************************************************************************
**	COPYRIGHT (c) 2018 huangzibin
**	author        :  hzb <hzbhlz@163.com>
**	date           :  2018.04.06
********************************************************************************/

#include "packet_parser.h"
#include "memory.h"
#include "stdio.h"
#include "stdlib.h"
#include "errno.h"
#include "fcntl.h"
#include "unistd.h"
int packet_parser_init(struct PacketParser* packet_parser, int fd, int max_packet_size,
						const char* packet_start_code, int startcode_len)
{
	int ret = 0;
	if (!packet_parser) {
		return -1;
	}
	if ((unsigned int)startcode_len > sizeof(packet_start_code)) {
		fprintf(stderr, "too long start code(%d, max:%d)\n", startcode_len, sizeof(packet_start_code));
		return -1;
	}
	char* buf = (char*)calloc(1, max_packet_size);
	if (!buf) {
		fprintf(stderr, "malloc failed\n");
		ret = -1;
		goto out;
	}
out:
	if (ret < 0) {
		free(buf);
		buf = NULL;
	}else {
		packet_parser->fd = fd;
		packet_parser->buf = buf;
		packet_parser->buf_size = max_packet_size;
		memcpy(packet_parser->packet_start_code, packet_start_code, startcode_len);
		packet_parser->start_code_len = startcode_len;
	}
	return ret;
}

void packet_parser_deinit(struct PacketParser* packet_parser)
{
	if (!packet_parser)
		return;
	free(packet_parser->buf);
	memset(packet_parser, 0, sizeof(struct PacketParser));
	return;
}


static int read_file_block(int fd, char* buf, int total_size, int* eof)
{	
	int read_size = 0;
	int ret = 0;
	while(1) {
		if (read_size >= total_size) {
			ret = read_size;
			break;
		}
		ret = read(fd, buf, total_size-read_size);
		if (ret  < 0) {
			if(errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) {
				fprintf(stderr, "read failed, error %s\n", strerror(errno));
				goto out;
			}else {
				continue;
			}
		}
		if (ret == 0) {
			if (read_size == 0) {
				*eof = 1;
				ret = 0;
				goto out;
			}else {
				ret = read_size;
				goto out;
			}
		}
		buf+= ret;
		read_size+=ret;
	}
out:
	return ret;
}

static int relocate_start_code(struct PacketParser* packet_parser)
{
	int i = 0;	
	int find_start_code_flag = 0;
	int match_end_position = packet_parser->cur_data_len - (packet_parser->start_code_len - 1);
	if (match_end_position <= 0) {
		return 0;
	}
	for (i = 0; i < match_end_position; ++i) {
		if (memcmp(packet_parser->buf+i, packet_parser->packet_start_code, packet_parser->start_code_len) == 0){
			find_start_code_flag = 1;
			break;
		}
	}
	char* copy_start_pos = 0;
	int bytes_to_copy = 0;
	if (i == 0) {
		goto out;
	}
	copy_start_pos = packet_parser->buf + i;
	bytes_to_copy = packet_parser->cur_data_len - i;
	memmove(packet_parser->buf, copy_start_pos, bytes_to_copy);
	packet_parser->cur_data_len = bytes_to_copy;
out:
	if (find_start_code_flag > 0)
		return 1;
	else
		return 0;	
}
#if 0
//成功buf将以startcode开始，并从fd读入尽可能多的数据。
static int read_data_and_find_start_code(struct PacketParser* packet_parser, int* end_flag)
{
	int ret = 0;
	int find_start = 0;
	while(1) {
		find_start = relocate_start_code(packet_parser);
		int left_size = packet_parser->buf_size - packet_parser->cur_data_len;
		ret = read_file_block(packet_parser->fd, packet_parser->buf+packet_parser->cur_data_len, left_size, end_flag);
		if (*end_flag > 0) {// && packet_parser->cur_data_len <= packet_parser->start_code_len) {
			break;
		}else if (ret < 0) {
			return -1;
		}
		else {
			packet_parser->cur_data_len += ret;
		}
		if (find_start > 0) {
			break;
		}			
	}
	if (find_start > 0) {
		*end_flag = 0;
	}else {
		return 0;
	}
	return 0;
}
int packet_parser_get_one_packet(struct PacketParser* packet_parser, char* buf, int buf_size, int *size, int *end_flag, 
										IsPacketVaild* is_packet_valid)
{
	int ret = 0;
	if (!packet_parser || !size || !end_flag || !is_packet_valid) {
		return -1;
	}
	while(1) {
		ret = read_data_and_find_start_code(packet_parser, end_flag);
		if (ret < 0) {
			return ret;
		}
		if (*end_flag > 0) {
			return 0;
		}
		char* copy_start_pos = 0;
		int bytes_to_copy = 0;
		int got_packet = 0;
		if (is_packet_valid(packet_parser->buf, packet_parser->cur_data_len, size) == 0) {
			copy_start_pos = packet_parser->buf+1;
			bytes_to_copy = packet_parser->cur_data_len -1;
		}else {
			copy_start_pos = packet_parser->buf+*size;
			bytes_to_copy = packet_parser->cur_data_len - *size;		
			got_packet = 1;
			if (*size <= 0 || *size > buf_size) {
				fprintf(stderr, "fatal error, size invalid(%d max:%d)\n", *size, buf_size);
				return -1;
			}
			memcpy(buf, packet_parser->buf, *size);
		}
		if (bytes_to_copy < 0) {
			fprintf(stderr, "fatal error, size is too large\n");
			return -1;			
		}
		memmove(packet_parser->buf, copy_start_pos, bytes_to_copy);
		if (got_packet > 0) {
			break;
		}
	}
	return ret;
}								
#endif

int packet_parser_get_one_packet(struct PacketParser* packet_parser, char* buf, int buf_size, int *size, int *end_flag, 
										IsPacketVaild* is_packet_valid)
{
	int ret = 0;
	if (!packet_parser || !size || !end_flag || !is_packet_valid) {
		return -1;
	}
	ret = is_packet_valid(packet_parser->buf, packet_parser->cur_data_len, size);
	if (PRESULT_VALID == ret) {
		if (*size <= 0 || *size > packet_parser->cur_data_len) {
			fprintf(stderr, "fatal error, size invalid(%d max:%d)\n", *size, packet_parser->cur_data_len);
			return -1;
		}
		memcpy(buf, packet_parser->buf, *size);
		packet_parser->cur_data_len-=*size;
		memmove(packet_parser->buf, packet_parser->buf+*size, packet_parser->cur_data_len);
		*end_flag = 0;
		return 0;
	}
	while(1) {
		
		int left_size = packet_parser->buf_size - packet_parser->cur_data_len;
		ret = read_file_block(packet_parser->fd, packet_parser->buf+packet_parser->cur_data_len, 
								left_size, end_flag);
		if (ret < 0) {
			return -1;
		}
		else {
			packet_parser->cur_data_len += ret;
		}	
		
		if (*end_flag > 0) {
			if (packet_parser->cur_data_len == 0) {
				return 0;
			}
		}
		ret = relocate_start_code(packet_parser);
		if (ret == 0) {
			if (*end_flag > 0) {
				fprintf(stderr, "drop some invalid data\n");
				return -1;
			}else 
				continue;
		}
		ret = is_packet_valid(packet_parser->buf, packet_parser->cur_data_len, size);
		if (PRESULT_VALID == ret) {
			if (*size <= 0 || *size > packet_parser->cur_data_len) {
				fprintf(stderr, "fatal error, size invalid(%d max:%d)\n", *size, packet_parser->cur_data_len);
				return -1;
			}
			memcpy(buf, packet_parser->buf, *size);
			packet_parser->cur_data_len-=*size;
			memmove(packet_parser->buf, packet_parser->buf+*size, packet_parser->cur_data_len);
			*end_flag = 0;
			return 0;
		}else if (PRESULT_INVALID == ret) {
			memmove(packet_parser->buf, packet_parser->buf+1, packet_parser->cur_data_len-1);
			packet_parser->cur_data_len--;
			fprintf(stderr, "drop some invalid data\n");
			continue;
		}else if (PRESULT_INCOMPLETE == ret) {
			if (*end_flag > 0) {
				fprintf(stderr, "drop some invalid data\n");
				return 0;
			}else {
				continue;
			}
		}else {
			fprintf(stderr, "fatal error, invalid result:%d\n", ret);
		}
		continue;
	}
	return ret;
}

void packet_parser_set_fd(struct PacketParser* packet_parser, int fd)
{
	if (!packet_parser) {
		return ;
	}
	packet_parser->fd = fd;
	packet_parser->cur_data_len = 0;
	return;
	
}

void packet_parser_clear_buf(struct PacketParser* packet_parser)
{
	if (!packet_parser) {
		return ;
	}
	packet_parser->cur_data_len = 0;
	return;
	
}

#if 0
typedef struct Stream_Head
{
	unsigned int	Syncode;			// 同步头，值为：SYN_START_CODE； 
	unsigned short	width;				// 视频图像宽度（对音频数据该值为：0）；
	unsigned short	height; 			// 视频图像高度（对音频数据该值为：0）； 
	unsigned char	streamType; 		// 数据流类型, 0:视频包; 1:音频包; 2:智能包, 见 PACK_TYPE_E
	unsigned char	frameHeadLen;		// 帧头长度,该长度根据packType 的值变化而取 sizeof(不同的结构体)
	unsigned char	chType; 			// 0, 主码流; 1, 从码流
	unsigned char	codecInfo;			// 编码类型，不同的编码对应解码用；音视频分别使用自己的编码方式；
	unsigned int	frameLen;			// 帧裸流长度， 除帧头之外的所有数据帧载荷大小（单位：BYTE），包括帧尾校验码； */
	unsigned int	frameNom;			 // 帧号,单调递增
	unsigned int	timeStamp;		// 从底层获取的时间戳,(毫秒) 
	unsigned char	frameType;			// 视频:帧类型 5,I帧; 1,P帧 . //modify to		codecInfo for  音频: 默认值 0
	unsigned char	videoStandard;		// 视频:标准 0,PAL; 1,NTSC. // 音频:通道模式, 0:单通道, 1:立体声, 默认值 0
	char	reserved[2];			//	预留
}Stream_Head_t, *pStream_Head_t;


#define MAX_PACKET_SIZE (128*1024)



int is_packet_vaild(const char* packet_buf, int buf_size, int* packet_size)
{
	struct Stream_Head* head = (struct Stream_Head*)packet_buf;
	int frame_size = head->frameHeadLen + head->frameLen;
	if (frame_size > MAX_PACKET_SIZE) {
		fprintf(stderr, "packet error, too large length(len:%d max:%d)\n", frame_size, MAX_PACKET_SIZE);
		return PRESULT_INVALID;
	}
	if (frame_size > buf_size) {
//		fprintf(stderr, "packet error(len:%d max:%d)\n", frame_size, buf_size);
		return PRESULT_INCOMPLETE;
	}
	char packet_end_code[] = {0x68,0x84,0xFA,0xF0};
	const char* buf = packet_buf + frame_size - 4;
	if (0 == memcmp(buf, packet_end_code, 4)) {
		*packet_size = frame_size;
		return PRESULT_VALID;
	} else
		fprintf(stderr, "packet error, skip\n");
	return PRESULT_INVALID;
}

int main()
{
	int fd = 0;
	const char* file_name = "1.dat";
	fd = open("1.dat", O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "open file(%s) failed, error:%s\n", file_name, strerror(errno));
		return -1;
	}
	struct PacketParser packet_parser = {0};
	char packet_start_code[] = {0x94,0x19,0xA5,0xA0};
	//int max_packet_size = 128*1024;
	int ret = packet_parser_init(&packet_parser, fd, MAX_PACKET_SIZE, packet_start_code, sizeof(packet_start_code));
	if (ret < 0) {
		fprintf(stderr, "packet_parser_init failed\n");
		return -1;
	}
	int index = 0;
	char packet[MAX_PACKET_SIZE] = {0};
	while(1) {
		int size = 0;
		int end_flag = 0;
		ret = packet_parser_get_one_packet(&packet_parser, packet, MAX_PACKET_SIZE,
													&size, &end_flag, is_packet_vaild);
		if (ret < 0) {
			fprintf(stderr, "packet_parser_get_one_packet failed\n");
			return -1;
		}
		if (end_flag) {
			printf("stream end\n");
			break;
		}
		struct Stream_Head* head = (struct Stream_Head*)packet;
		printf("get one packet, size:%d\n", size);
		fprintf(stdout, "frame %d:\r\n"
			"stream_type %d\r\n"
			"frame_type %d\r\n"
			"channel_type %d\r\n"
			"data_len %d\r\n"
			"pts %d\r\n"
			"framenum %d\r\n",
			index++, 
			head->streamType,
			head->frameType,
			head->chType ,
			head->frameLen,
			head->timeStamp,
			head->frameNom);
		printf("\n\n");
		static int frame_num = 0;
		if (frame_num == 0) {
			frame_num = head->frameNom;
		}else {
			if (frame_num + 1 != head->frameNom) {
				fprintf(stderr, "frame number not match\n");
				getchar();	
			}	
			frame_num = head->frameNom;
		}	
	}
	packet_parser_deinit(&packet_parser);
	close(fd);
	return 0;
}
#endif
